package cn.fenqing168.nio;

import lombok.SneakyThrows;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.nio.charset.StandardCharsets;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.*;

/**
 * @author fenqing
 */
public class NioServer1 {

    public static void main(String[] args) throws IOException {
        //准备线程池
        ExecutorService pool = new ThreadPoolExecutor(10, 20, 100, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<>(10),
                Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        //准备一个ServerSocketChannel
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //准备一个Selector
        Selector selector = Selector.open();
        //ServerSocketChannel绑定一个端口
        serverSocketChannel.bind(new InetSocketAddress(9999));
        //ServerSocketChannel切换至非堵塞模式
        serverSocketChannel.configureBlocking(false);
        //ServerSocketChannel注册到Selector
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        //轮询
        while (selector.select() > 0){
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()){
                SelectionKey selectionKey = iterator.next();
                if (selectionKey.isAcceptable()) {
                    SelectableChannel channel = selectionKey.channel();
                    acceptable((ServerSocketChannel) channel, selector);
                }
                if(selectionKey.isReadable()){
                    SelectableChannel channel = selectionKey.channel();
                    ByteBuffer buffer = (ByteBuffer) selectionKey.attachment();
                    readable((SocketChannel) channel, buffer);
                }
                iterator.remove();
            }
        }
        //发现读事件
        //获取SocketChannel
        //开始读取
        //读取完后删除事件的数据
    }


    /**
     * 连接事件
     * @param serverSocketChannel
     * @param selector
     */
    public static void acceptable(ServerSocketChannel serverSocketChannel, Selector selector){
        System.out.println("获得了连接");
        //发现连接事件，获取SocketChannel
        SocketChannel socketChannel = null;
        try {
            socketChannel = serverSocketChannel.accept();
            //切换非堵塞模式
            socketChannel.configureBlocking(false);
            //注册到Selector
            socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 读取事件
     */
    @SneakyThrows
    public static void readable(SocketChannel channel, ByteBuffer byteBuffer){
        System.out.println("可读了");
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int len;
        while ((len = channel.read(byteBuffer)) > 0){
            baos.write(byteBuffer.array(), 0, len);
            byteBuffer.clear();
        }
        channel.close();
        System.out.println(new String(baos.toByteArray(), StandardCharsets.UTF_8));
    }

}
